﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.IO;
using System.Management;
using System.Xml.Linq;
using System.Xml.XPath;
using System.ServiceProcess;
using System.Data.Sql;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using IRDev.Library.ExpandedException.Factory;

namespace AutoDeploy.Common.Library
{
    /// <summary>
    /// Element grouping 
    /// From IRDev Library Project by Mark Rowe markwrowe@hotmail.com  http://everythingworkflow.spaces.live.com  ,  Daniel Turnell daniel.turnell@gmail.com
    /// This Project http://autodeploy.codeplex.com
    /// </summary>
    public static class ExternalHelper
    {

        /// <summary>
        /// registryEntryExistsInLocalMachine
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool registryEntryExistsInLocalMachine(this string key)
        {
            List<string> Params = new List<string>();
            Params.Add(string.Format("String key:{0}", key));
            Microsoft.Win32.RegistryKey localMachine = Microsoft.Win32.Registry.LocalMachine;
            try
            {
                Microsoft.Win32.RegistryKey keyToSearch = localMachine.OpenSubKey(key);
                foreach (string s in keyToSearch.GetSubKeyNames().ToList())
                {
                    //has some subkey name therefore that registry entry is there.
                    return true;
                }
                return false;
            }
            catch (IRDev.Library.ExpandedException.Common.ExpandedException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                IRDev.Library.ExpandedException.Common.ExpandedException ee = ex.CreateAndReturnExpandedException(StringHelper.ListOfStringToString(Params, true), "ExternalHelper", "registryEntryExistsInLocalMachine");
                throw ee;
            }

        }
        /// <summary>
        /// isInstalled
        /// </summary>
        /// <param name="searchFor"></param>
        /// <param name="isExact"></param>
        /// <returns></returns>
        public static bool isInstalled(this string searchFor, bool isExact)
        {
            List<string> Params = new List<string>();
            Params.Add(string.Format("String searchFor:{0}", searchFor));
            Params.Add(string.Format("String isExact:{0}", (isExact ? "true" : "false")));
            try
            {
                if (isExact)
                {
                    return ReturnListOfInstalledPrograms().ListValueMatch(searchFor, isExact);
                }
                return ReturnListOfInstalledPrograms().ListValueContains(searchFor, false);
            }
            catch (IRDev.Library.ExpandedException.Common.ExpandedException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                IRDev.Library.ExpandedException.Common.ExpandedException ee = ex.CreateAndReturnExpandedException(StringHelper.ListOfStringToString(Params, true), "ExternalHelper", "isInstalled");
                throw ee;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="searchFor"></param>
        /// <param name="isExact"></param>
        /// <returns></returns>
        public static bool isServiceInstalled(string searchFor, bool isExact)
        {
            List<string> Params = new List<string>();
            Params.Add(string.Format("String searchFor:{0}", searchFor));
            Params.Add(string.Format("String isExact:{0}", (isExact ? "true" : "false")));
            try
            {
                if (isExact)
                {
                    return ReturnListOfInstalledServices().ListValueMatch(searchFor, false);
                }
                return ReturnListOfInstalledServices().ListValueContains(searchFor, false);
            }
            catch (IRDev.Library.ExpandedException.Common.ExpandedException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                IRDev.Library.ExpandedException.Common.ExpandedException ee = ex.CreateAndReturnExpandedException(StringHelper.ListOfStringToString(Params, true), "ExternalHelper", "isServiceInstalled");
                throw ee;
            }
        }
        /// <summary>
        /// For now only works on single strings
        /// </summary>
        /// <param name="uri"></param>
        /// <returns></returns>
        public static string FormatForProgramFiles(this string uri)
        { 
            List<string> Params = new List<string>();
            try
            {
                List<string> ls = new List<string>();
                bool found = false;
                if (Environment.Is64BitOperatingSystem)
                {
                    ls.Add(uri.Replace("[Program Files]", Environment.GetEnvironmentVariable("ProgramFiles(x86)")));
                    ls.Add(uri.Replace("[Program Files]", Environment.GetEnvironmentVariable("ProgramFiles")));
                }
                else
                {
                    ls.Add(uri.Replace("[Program Files]", Environment.GetEnvironmentVariable("ProgramFiles")));
                }
                foreach (string s in ls)
                {
                    if (File.Exists(s) || Directory.Exists(s))
                    {
                        uri = s.Trim();
                        found = true;
                    }
                }
                if (found)
                {
                    return uri;
                }
                else
                {
                    return string.Empty;
                }
            }
            catch (IRDev.Library.ExpandedException.Common.ExpandedException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                IRDev.Library.ExpandedException.Common.ExpandedException ee = ex.CreateAndReturnExpandedException(StringHelper.ListOfStringToString(Params, true), "ExternalHelper", "ReturnListOfInstalledPrograms");
                throw ee;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public static List<string> ReturnListOfInstalledPrograms()
        {
            List<string> Params = new List<string>();
            List<string> ls = new List<string>();
            try
            {
                //There is no Microsoft.Win64 
                Microsoft.Win32.RegistryKey localMachine = Microsoft.Win32.Registry.LocalMachine;
                Microsoft.Win32.RegistryKey uninstall = localMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall");
                foreach (string applicationSubKeyName in uninstall.GetSubKeyNames().ToList())
                {
                    Microsoft.Win32.RegistryKey currentApp = uninstall.OpenSubKey(applicationSubKeyName);
                    if (currentApp.GetValue("DisplayName") != null)
                    {
                        ls.Add(currentApp.GetValue("DisplayName").ToString());
                    }
                    currentApp.Close();
                }
                uninstall.Close();
                localMachine.Close();

                ls.Sort();
                return ls;
            }
            catch (IRDev.Library.ExpandedException.Common.ExpandedException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                IRDev.Library.ExpandedException.Common.ExpandedException ee = ex.CreateAndReturnExpandedException(StringHelper.ListOfStringToString(Params, true), "ExternalHelper", "ReturnListOfInstalledPrograms");
                throw ee;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public static List<string> ReturnListOfInstalledServices()
        {
            List<string> Params = new List<string>();
            try
            {
                List<string> ls = new List<string>();
                foreach (ServiceController sc in ServiceController.GetServices().ToList())
                {
                    ls.Add(sc.ServiceName);
                }
                return ls;
            }
            catch (IRDev.Library.ExpandedException.Common.ExpandedException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                IRDev.Library.ExpandedException.Common.ExpandedException ee = ex.CreateAndReturnExpandedException(StringHelper.ListOfStringToString(Params, true), "ExternalHelper", "ReturnListOfInstalledServices");
                throw ee;
            }
        }
        /// <summary>
        /// RunShellCommand
        /// Runs a simple Command line. 
        /// </summary>
        /// <param name="commandToRun"></param>
        public static void RunShellCommand(string commandToRun)
        {
            List<string> Params = new List<string>();
            Params.Add(string.Format("String commandToRun:{0}", commandToRun));
            try
            {
                Process p = System.Diagnostics.Process.Start(commandToRun);
                p.WaitForExit();
            }
            catch (IRDev.Library.ExpandedException.Common.ExpandedException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                IRDev.Library.ExpandedException.Common.ExpandedException ee = ex.CreateAndReturnExpandedException(StringHelper.ListOfStringToString(Params, true), "ExternalHelper", "RunShellCommand");
                throw ee;
            }
        }
        /// <summary>
        /// RunShellCommand
        /// </summary>
        /// <param name="commandToRun"></param>
        /// <param name="user"></param>
        /// <param name="password"></param>
        public static void RunShellCommand(string commandToRun, string user, string password)
        {
            List<string> Params = new List<string>();
            Params.Add(string.Format("String commandToRun:{0}", commandToRun));
            Params.Add(string.Format("String user:{0}", user));
            Params.Add(string.Format("String password:{0}", password));
            try
            {
                string domain = string.Empty;
                if (user.Contains("\\"))
                {
                    domain = user.Substring(0, user.IndexOf("\\")).Replace("\\", "");
                    user = user.Substring(user.IndexOf("\\")).Replace("\\", "");
                }
                if (user.Contains("@"))
                {
                    domain = user.Substring(user.IndexOf("@")).Replace("@", "");
                    user = user.Substring(0, user.IndexOf("@")).Replace("@", "");
                }
                System.Security.SecureString pass = new System.Security.SecureString();
                foreach (char c in password)
                {
                    pass.AppendChar(c);
                }
                Process p = System.Diagnostics.Process.Start(commandToRun, user, pass, domain);
                p.WaitForExit();
            }
            catch (IRDev.Library.ExpandedException.Common.ExpandedException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                IRDev.Library.ExpandedException.Common.ExpandedException ee = ex.CreateAndReturnExpandedException(StringHelper.ListOfStringToString(Params, true), "ExternalHelper", "RunShellCommand");
                throw ee;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="uri"></param>
        /// <returns></returns>
        public static bool FileExists(string uri)
        {
            List<string> Params = new List<string>();
            Params.Add(string.Format("String uri:{0}",uri));
            try
            {
                return File.Exists(uri);
            }
            catch (IRDev.Library.ExpandedException.Common.ExpandedException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                IRDev.Library.ExpandedException.Common.ExpandedException ee = ex.CreateAndReturnExpandedException(StringHelper.ListOfStringToString(Params, true), "ExternalHelper", "RunShellCommand");
                throw ee;
            }
        }
        /// <summary>
        /// DirectoryExists
        /// </summary>
        /// <param name="uri"></param>
        /// <returns></returns>
        public static bool DirectoryExists(string uri)
        {
            List<string> Params = new List<string>();
            Params.Add(string.Format("String uri:{0}", uri));
            try
            {
                return Directory.Exists(uri);
            }
            catch (IRDev.Library.ExpandedException.Common.ExpandedException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                IRDev.Library.ExpandedException.Common.ExpandedException ee = ex.CreateAndReturnExpandedException(StringHelper.ListOfStringToString(Params, true), "ExternalHelper", "RunShellCommand");
                throw ee;
            }
        }
        /// <summary>
        /// CheckForFileLocation
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool CheckForFileLocation(ref string s)
        {
            List<string> Params = new List<string>();
            Params.Add(string.Format("String s:{0}", s));
            try
            {
                bool isQuoted = s.Contains("\"[Program Files]");
                string pre = string.Empty;
                string post = string.Empty;
                string file = string.Empty;
                string temp = string.Empty;
                int Preindex = s.IndexOf("[Program Files]");
                if (Preindex > -1)
                {
                    if (isQuoted)
                    {
                        pre = (Preindex > 0 ? s.Substring(0, Preindex) : "");
                        temp = (pre.Length != 0 ? s.Replace(pre, "") : s);
                        file = temp.Substring(0, temp.LastIndexOf("\""));
                        post = temp.Replace(file, "");
                    }
                    else
                    {
                        pre = (Preindex > 0 ? s.Substring(0, Preindex) : "");
                        temp = (pre.Length != 0 ? s.Replace(pre, "") : s);
                        file = temp;
                        post = temp.Replace(file, "");
                    }
                    if (isFileInLocation(ref file))
                    {
                        s = pre + file + post;
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    if (isFileInLocation(ref s))
                    {

                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }

            }
            catch (IRDev.Library.ExpandedException.Common.ExpandedException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                IRDev.Library.ExpandedException.Common.ExpandedException ee = ex.CreateAndReturnExpandedException(StringHelper.ListOfStringToString(Params, true), "ExternalHelper", "CheckForFileLocation");
                throw ee;
            }
        }
        /// <summary>
        /// isFileInLocation
        /// </summary>
        /// <param name="uri"></param>
        /// <returns></returns>
        public static bool isFileInLocation(ref string uri)
        {
            List<string> Params = new List<string>();
            Params.Add(string.Format("String uri:{0}", uri));
            try
            {
                List<string> ls = new List<string>();
                if (Environment.Is64BitOperatingSystem)
                {
                    ls.Add(uri.Replace("[Program Files]", Environment.GetEnvironmentVariable("ProgramFiles(x86)")));
                    ls.Add(uri.Replace("[Program Files]", Environment.GetEnvironmentVariable("ProgramFiles")));
                }
                else
                {
                    ls.Add(uri.Replace("[Program Files]", Environment.GetEnvironmentVariable("ProgramFiles")));
                }
                foreach (string s in ls)
                {
                    if (File.Exists(s))
                    {
                        uri = s.Trim();
                        return true;
                    }
                }
                uri = string.Empty;
                return false;
            }
            catch (IRDev.Library.ExpandedException.Common.ExpandedException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                IRDev.Library.ExpandedException.Common.ExpandedException ee = ex.CreateAndReturnExpandedException(StringHelper.ListOfStringToString(Params, true), "ExternalHelper", "isFileInLocation");
                throw ee;
            }
        }

        /// <summary>
        /// Base ADO ExecuteNonQuery
        /// </summary>
        /// <param name="statementToRun"></param>
        /// <param name="connString"></param>
        public static void ExecuteNonQuery(string statementToRun, string connString)
        {
            List<string> Params = new List<string>();
            Params.Add(string.Format("String statementToRun:{0}", statementToRun));
            Params.Add(string.Format("String connString:{0}", connString));
            SqlConnection sqlConn = new SqlConnection(connString);
            SqlCommand sqlCommand = new SqlCommand(statementToRun, sqlConn);
            SqlDataAdapter sqlDataAdapter = new SqlDataAdapter();
            try
            {
                sqlConn.Open();
                sqlDataAdapter.SelectCommand = sqlCommand;
                sqlDataAdapter.SelectCommand.ExecuteNonQuery();
            }
            catch (IRDev.Library.ExpandedException.Common.ExpandedException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                IRDev.Library.ExpandedException.Common.ExpandedException ee = ex.CreateAndReturnExpandedException(StringHelper.ListOfStringToString(Params, true), "ExternalHelper", "ExecuteNonQuery");
                throw ee;
            }
            finally
            {
                sqlConn.Close();
            }
            sqlConn.Close();
        }
        /// <summary>
        /// Runs a generic ExecuteNonQuery using a file as SQL command
        /// </summary>
        /// <param name="uri"></param>
        /// <param name="connString"></param>
        public static void RunSqlScript(string uri, string connString)
        {
            List<string> Params = new List<string>();
            Params.Add(string.Format("String uri:{0}", uri));
            Params.Add(string.Format("String connString:{0}", connString));
            try
            {
                ExecuteNonQuery(ReadAFile(uri), connString);
            }
            catch (IRDev.Library.ExpandedException.Common.ExpandedException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                IRDev.Library.ExpandedException.Common.ExpandedException ee = ex.CreateAndReturnExpandedException(StringHelper.ListOfStringToString(Params, true), "ExternalHelper", "RunSqlScript");
                throw ee;
            }
        }
        /// <summary>
        /// Runs a generic ExecuteNonQuery
        /// </summary>
        /// <param name="uri"></param>
        /// <param name="connString"></param>
        public static void RunSqlCommand(string command, string connString)
        {
            List<string> Params = new List<string>();
            Params.Add(string.Format("String command:{0}", command));
            Params.Add(string.Format("String connString:{0}", connString));
            try
            {
                ExecuteNonQuery(command, connString);
            }
            catch (IRDev.Library.ExpandedException.Common.ExpandedException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                IRDev.Library.ExpandedException.Common.ExpandedException ee = ex.CreateAndReturnExpandedException(StringHelper.ListOfStringToString(Params, true), "ExternalHelper", "RunSqlCommand");
                throw ee;
            }
        }
        /// <summary>
        /// Takes Text out of a file.
        /// </summary>
        /// <param name="uri"></param>
        /// <returns></returns>
        public static string ReadAFile(string uri)
        {
            List<string> Params = new List<string>();
            Params.Add(string.Format("String uri:{0}", uri));
            try
            {
                if (File.Exists(uri))
                {
                    return File.ReadAllText(uri);
                }
                return string.Empty;
            }
            catch (IRDev.Library.ExpandedException.Common.ExpandedException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                IRDev.Library.ExpandedException.Common.ExpandedException ee = ex.CreateAndReturnExpandedException(StringHelper.ListOfStringToString(Params, true), "ExternalHelper", "ReadAFile");
                throw ee;
            }
        }
        /// <summary>
        /// Standard Wrapper to WriteAFile
        /// </summary>
        /// <param name="myWrite">What to enter into File</param>
        /// <param name="fileToWrite"></param>
        /// <param name="appendToFile"></param>
        public static void WriteAFile(string myWrite, string fileToWrite, bool appendToFile)
        {
            List<string> Params = new List<string>();
            Params.Add(string.Format("String myWrite:{0}", myWrite));
            Params.Add(string.Format("String fileToWrite:{0}", fileToWrite));
            Params.Add(string.Format("String appendToFile):{0}", (appendToFile ? "true" : "false")));
            try
            {
                using (StreamWriter sw = new StreamWriter(fileToWrite, appendToFile))
                {
                    sw.WriteLine(myWrite);
                }
            }
            catch (IRDev.Library.ExpandedException.Common.ExpandedException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                IRDev.Library.ExpandedException.Common.ExpandedException ee = ex.CreateAndReturnExpandedException(StringHelper.ListOfStringToString(Params, true), "ExternalHelper", "WriteAFile");
                throw ee;
            }
        }
        /// <summary>
        /// Standard Wrapper to WriteAFile
        /// </summary>
        /// <param name="myWrite">What to enter into File (Each String )</param>
        /// <param name="fileToWrite"></param>
        /// <param name="appendToFile"></param>
        public static void WriteAFile(List<string> myWrite, string fileToWrite, bool appendToFile)
        {
            List<string> Params = new List<string>();
            Params.Add(string.Format("String myWrite:{0}", StringHelper.ListOfStringToString(myWrite,true)));
            Params.Add(string.Format("String fileToWrite:{0}", fileToWrite));
            Params.Add(string.Format("String appendToFile):{0}", (appendToFile ? "true" : "false")));
            try
            {
                using (StreamWriter sw = new StreamWriter(fileToWrite, appendToFile))
                {
                    foreach (string s in myWrite)
                    {
                        sw.WriteLine(s + "\n");
                    }
                }
            }
            catch (IRDev.Library.ExpandedException.Common.ExpandedException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                IRDev.Library.ExpandedException.Common.ExpandedException ee = ex.CreateAndReturnExpandedException(StringHelper.ListOfStringToString(Params, true), "ExternalHelper", "WriteAFile");
                throw ee;
            }
        }
    }
}